﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using MovieRental.Entities;
using MovieRental.DataInterfaces;
using MovieRental.BuisnessComponents.Exceptions;
using MovieRental.BuisnessComponents.Helpers;
using MovieRental.BuisnessComponents.Base;

namespace MovieRental.BuisnessComponents
{
    public class MovieComponent : BaseComponent<MovieInfo, Guid, IMovieRepository>
    {
        public MovieComponent(IMovieRepository repository)
            : base(repository)
        {
        }

        private const string urlRegex = @"^http\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$";

        public bool VerifyImdbRating(double rating)
        {
            return !(rating <= 0 || rating > 10.0);
        }

        public bool VerifyWebPage(string webPage)
        {
            if (string.IsNullOrEmpty(webPage))
                return false;
            return new Regex(urlRegex).IsMatch(webPage);
        }

        public override void Verify(MovieInfo movie)
        {
            if (string.IsNullOrWhiteSpace(movie.Title))
                throw new EmptyFieldException(movie, "Title");
            if (!VerifyImdbRating(movie.ImdbRating))
                throw new FieldValueRangeException<double>(movie, "ImdbRating", 0, 10);
            if (!VerifyWebPage(movie.WebPage))
                throw new RegexException(movie, "WebPage");     
        }


        public bool CanDelete(MovieInfo movie)
        {
            var loanCartComponent = ComponentFactory.Instance.GetLoanCartComponent();
            return loanCartComponent.GetNotReturnedLoansForMovieCount(movie) == 0;
        }


        public IEnumerable<MovieInfo> SearchMoviesByTitle(string searchString)
        {
            if (string.IsNullOrEmpty(searchString))
                return GetAll();
            string[] words = searchString.Split(' ');
            var request = from movie in Repository.LoadAll()
                          where movie.Title.GetSimilarWordsCoefficient(searchString) > 0
                          orderby movie.Title.GetSimilarWordsCoefficient(searchString) descending
                          select movie;
            return request;
        }

        public IEnumerable<MovieInfo> GetMostPopularMovies(int count)
        {
            var loanCartComponent = ComponentFactory.Instance.GetLoanCartComponent();
            var query = GetAll().OrderByDescending(x => loanCartComponent.GetAllLoansCountForMovie(x));
            return query.Take(count);
        }

        public IEnumerable<MovieInfo> GetNotPopularMovies(int count)
        {
            var loanCartComponent = ComponentFactory.Instance.GetLoanCartComponent();
            var query = GetAll().OrderBy(x => loanCartComponent.GetAllLoansCountForMovie(x));
            return query.Take(count);
        }


    }
}
